package com.sz.biz.pay.account.service.impl;

import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.common.utils.NOGenerator;
import com.sz.biz.pay.account.dto.MemberTransactionDto;
import com.sz.biz.pay.account.dto.OrderPaymentDto;
import com.sz.biz.pay.account.dto.PayTransactionDto;
import com.sz.biz.pay.account.dto.TransactionDetailsDto;
import com.sz.biz.pay.account.entity.Account;
import com.sz.biz.pay.account.entity.ThirdPayAccount;
import com.sz.biz.pay.account.entity.Transaction;
import com.sz.biz.pay.account.service.*;
import com.sz.biz.pay.constants.PayAction;
import com.sz.biz.pay.constants.PayConstant;
import com.sz.biz.pay.transfer.dto.NotifyDataDto;
import com.sz.biz.pay.util.BackDataUtil;
import com.sz.biz.trade.bill.service.TrdBillingService;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.Pagination;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.i18n.I18nMessageHelper;
import com.sz.common.base.utils.StringUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.pay.common.DateGenerator;
import com.sz.common.pay.common.SequenceGenerator;
import com.sz.common.pay.pingan.constant.CcyCode;
import com.sz.common.pay.pingan.constant.Constant;
import com.sz.common.pay.pingan.core.client.PAPay;
import com.sz.common.pay.pingan.entity.b2b.transfer.AccountRecheckPaymentRequest;
import com.sz.common.pay.pingan.entity.b2b.transfer.AccountRecheckPaymentResponse;
import com.sz.common.pay.pingan.entity.b2b.transfer.PlatformOperationPaymentRequest;
import com.sz.common.pay.pingan.entity.b2b.transfer.PlatformOperationPaymentResponse;
import com.sz.common.pay.pingan.entity.query.TimePeriodTransactionDetailsRequest;
import com.sz.common.pay.pingan.entity.query.TimePeriodTransactionDetailsResponse;
import com.sz.common.pay.pingan.entity.transfer.MemberTransactionPasswordRequest;
import com.sz.common.pay.pingan.exception.NoAvailableConnectException;
import com.sz.common.pay.pingan.exception.OperationFailedException;
import com.sz.common.pay.pingan.exception.PayCommonException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.sz.common.pay.common.DateGenerator.*;


/**
 * Function: TODO: ADD FUNCTION <br>
 * Author: HeWenBo <br>
 * Date: 2017-12-05 09:30:00
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private TransactionService transactionService;

    @Autowired
    private ThirdPayAccountService thirdPayAccountService;

    @Autowired
    private BankCardService bankCardService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private TrdBillingService trdBillingService;


    /**
     * 通过账单号查询交易详情
     *
     * @param billNo
     * @return
     */
    @Override
    public Map<String, Object> findTransactionByBillNo(String billNo) {
        Transaction transaction = transactionService.findByBillNo(billNo);
        Map<String, Object> map = new HashMap<>(16);
        if (null != transaction) {
            map.put("billNo", transaction.getBillNo());
            map.put("tranTime", getDateByYYYYMMDDHHMMSSString(transaction.getTranDate() + transaction.getTranTime()));
            map.put("tranAmount", transaction.getTranAmount() + transaction.getCurrency());
            map.put("tranStatus", transaction.getTranStatus());
            if ((PayConstant.TranscationType.WITHDRAWAL == transaction.getTranType()) || (PayConstant.TranscationType.PAY == transaction.getTranType())) {
                map.put("AccountId", transaction.getOutThirdPayAccountId());
                map.put("AccountName", transaction.getOutThirdPayAccountName());
                map.put("bankName", transaction.getInAccountName());
                map.put("bankCarNo", transaction.getInAccountId());
            } else if (PayConstant.TranscationType.RECHARGE == transaction.getTranType()) {
                map.put("AccountId", transaction.getInThirdPayAccountId());
                map.put("AccountName", transaction.getInThirdPayAccountName());
                map.put("bankName", transaction.getOutAccountName());
                map.put("bankCarNo", transaction.getOutAccountId());
            }
        }
        return map;
    }

    /**
     * 按条件查询交易信息
     *
     * @param id
     * @param q
     * @param pageIndex
     * @param pageSize
     * @param beginDate
     * @param endDate
     * @param tranType
     * @return
     */
    @Override
    public QResultDto findTransactionList(String id, String q, int pageIndex, int pageSize, String beginDate, String endDate, String tranType) {
        //银行不支持按账单号和账户持有人进行查询，所有按这两个条件查询时从平台数据库查，否则从平安银行接口查询
        //目前无法调用银行接口查询流水，先注释掉使用平台数据库查询，银行接口正常后再放开这段代码
        //if(q.isEmpty() && tranType.isEmpty()){
        //    return findTransactionListFromBank(id,pageIndex,pageSize,beginDate,endDate);
        //}else{
        return findTransactionListFromDB(id, q, pageIndex, pageSize, beginDate, endDate, tranType);
        //}
    }

    /**
     * 从平台数据库查询交易列表
     *
     * @param id
     * @param q
     * @param pageIndex
     * @param pageSize
     * @param beginDate
     * @param endDate
     * @param tranType
     * @return
     */
    private QResultDto findTransactionListFromDB(String id, String q, int pageIndex, int pageSize, String beginDate, String endDate, String tranType) {
        q = StringUtils.replaceSqlPattern(q);
        QueryParams params = new QueryParams(pageSize, pageIndex, q, null);
        params.put("ThirdPayAccountId", id);
        params.put("tranType", tranType);
        if ((!endDate.isEmpty()) && (!beginDate.isEmpty())) {
            params.put("beginDate", getyyyyMMdd(getDateStringByYYYY_MM_DDString(beginDate)));
            params.put("endDate", getyyyyMMdd(getDateStringByYYYY_MM_DDString(endDate)));
        }
        QResultDto qResultDto = transactionService.findByQuery(params);
        List<Transaction> transactionList = (List<Transaction>) qResultDto.getData();
        List<Map<String, Object>> list = new ArrayList<>();
        for (Transaction transaction : transactionList) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", transaction.getId());
            map.put("tranTime", getDateByYYYYMMDDHHMMSSString(transaction.getTranDate() + transaction.getTranTime()));
            if (PayConstant.TranscationType.PAY == transaction.getTranType()) {
                map.put("thirdPayAccountName", transaction.getInThirdPayAccountName());
            }
            map.put("billNo", transaction.getBillNo());
            map.put("tranAmount", transaction.getTranAmount() +
                    transaction.getCurrency());
            map.put("tranType", tranTypeConvert(transaction.getTranType()));
            map.put("tranTypeCode", transaction.getTranType());
            list.add(map);
        }
        qResultDto.setData(list);
        return qResultDto;
    }

    /**
     * 从平安银行接口查询交易列表
     *
     * @param id
     * @param pageIndex
     * @param pageSize
     * @param beginDate
     * @param endDate
     * @return
     */
    private QResultDto findTransactionListFromBank(String id, int pageIndex, int pageSize, String beginDate, String endDate) {
        //平台查询按每页10个数据，银行接口每次返回20个数据，对银行查询传入PageIndex时进行如下转换
        int pageIndexConvert = (int) Math.round(pageIndex / 2.0);
        ThirdPayAccount thirdPayAccount = thirdPayAccountService.findById(id);
        String thirdLogNo = SequenceGenerator.getThirdLogNo();
        TimePeriodTransactionDetailsRequest timePeriodTransactionDetailsRequest = new TimePeriodTransactionDetailsRequest();
        timePeriodTransactionDetailsRequest.setCustAcctId(thirdPayAccount.getThirdPayId());
        if (beginDate.isEmpty() || endDate.isEmpty()) {
            timePeriodTransactionDetailsRequest.setFuncFlag(Constant.TimePeriodTransactionFuncFlag.NOW);
        } else {
            timePeriodTransactionDetailsRequest.setFuncFlag(Constant.TimePeriodTransactionFuncFlag.HISTORY);
            beginDate = getyyyyMMdd(getDateByYYYYMMDD_HHMMSSString(beginDate));
            endDate = getyyyyMMdd(getDateByYYYYMMDD_HHMMSSString(endDate));
        }
        timePeriodTransactionDetailsRequest.setBeginDate(beginDate);
        timePeriodTransactionDetailsRequest.setEndDate(endDate);
        timePeriodTransactionDetailsRequest.setSupAcctId(Constant.SUP_ACCT_ID);
        timePeriodTransactionDetailsRequest.setSelectFlag(Constant.TimePeriodTransactionSelectFlag.IN);
        timePeriodTransactionDetailsRequest.setPageNum(pageIndexConvert + "");
        TimePeriodTransactionDetailsResponse timePeriodTransactionDetailsResponse = null;
        Object object = null;
        QResultDto qResultDto = new QResultDto();
        //特别重要：每个请求与响应都要记录到，数据库日志里表里（sys_operation_log），包括数据.这是交易排查的重要数据
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.PAY, makeBackData(thirdLogNo, timePeriodTransactionDetailsRequest));
        try {
            timePeriodTransactionDetailsResponse = (TimePeriodTransactionDetailsResponse) PAPay.sendMessage(thirdLogNo, timePeriodTransactionDetailsRequest, TimePeriodTransactionDetailsResponse.class);
            object = timePeriodTransactionDetailsResponse;
        } catch (NoAvailableConnectException e) {
            object = e.getMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_AVAILABLE_CONNECT);
        } catch (OperationFailedException e) {
            object = e.getErrorMessage();
            if (!(PayConstant.PayErrorCode.ERROR_NO_DATA.equals(e.getErrorMessage().getRspCode()))) {
                qResultDto.setErrorCode(ErrorCodes.ERROR_PAY_OPERATION.getCode());
                qResultDto.setMsg(I18nMessageHelper.getI18nMessage(ErrorCodes.ERROR_PAY_OPERATION.getMessageKey(), null));
                qResultDto.setData(e.getErrorMessage());
            } else {
                qResultDto.setData(new ArrayList());
            }
            return qResultDto;
        } catch (PayCommonException e) {
            object = e.getMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_COMMON);
        } finally {
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.PAY, makeBackData(thirdLogNo, object));
        }

        return makeTransactionListResult(timePeriodTransactionDetailsResponse, pageIndex, pageSize);
    }

    private QResultDto makeTransactionListResult(TimePeriodTransactionDetailsResponse timePeriodTransactionDetailsResponse, int pageIndex, int pageSize) {

        int recordNum = Integer.parseInt(timePeriodTransactionDetailsResponse.getRecordNum());
        int totalNum = Integer.parseInt(timePeriodTransactionDetailsResponse.getTotalCount());
        //平台查询按每页10个数据，银行接口每次返回20个数据，以下对pageSize进行转换
        int pageSizeStart = (pageIndex % 2 == 0) ? pageSize : 0;
        int pageSizeEnd = recordNum > pageSize ? pageSize : recordNum;
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = pageSizeStart; i < pageSizeEnd; i++) {
            Map<String, Object> map = new HashMap<>();
            Transaction transaction = transactionService.findByThirdLogNo(timePeriodTransactionDetailsResponse.getFrontLogNo()[i]);
            if (null != transaction) {
                map.put("id", transaction.getId());
                map.put("tranTime", getDateByYYYYMMDDHHMMSSString(timePeriodTransactionDetailsResponse.getTranDate()[i] + timePeriodTransactionDetailsResponse.getTranTime()[i]));
                map.put("thirdPayAccountName", transaction.getOutThirdPayAccountName());
                map.put("billNo", transaction.getBillNo());
                map.put("tranAmount", timePeriodTransactionDetailsResponse.getTranAmount()[i] +
                        transaction.getCurrency());
                map.put("tranType", tranTypeConvert(transaction.getTranType()));
                map.put("tranTypeCode", transaction.getTranType());
                list.add(map);
            }
        }

        Pagination pagination = new Pagination(pageSize, pageIndex);
        pagination.setTotalResult(totalNum);
        pagination.getCurrentResult();
        pagination.getCurrentPage();

        return new QResultDto(list, pagination);
    }

    private String tranTypeConvert(int tranType) {
        String tranTypeResult = "";
        if (PayConstant.TranscationType.RECHARGE == tranType) {
            tranTypeResult = "充值";
        } else if (PayConstant.TranscationType.WITHDRAWAL == tranType) {
            tranTypeResult = "提现";
        } else if (PayConstant.TranscationType.PAY == tranType) {
            tranTypeResult = "支付";
        } else if (PayConstant.TranscationType.OTHER == tranType) {
            tranTypeResult = "其他";
        } else if (PayConstant.TranscationType.DECREASE == tranType) {
            tranTypeResult = "减持";
        }
        return tranTypeResult;
    }

    /**
     * 计算手续费
     *
     * @param memberTransactionDto
     * @return
     */
    @Override
    public ResultDto transactionHandFee(MemberTransactionDto memberTransactionDto) {
        ResultDto dto = new ResultDto();
        //手续费暂时返回0
        dto.setData(0);
        return dto;
    }


    /**
     * 确认支付已经完成
     *
     * @param transaction
     * @param success
     */
    private void updateTranscation(Transaction transaction, int success) {
        transaction.setTranStatus(success);
        transactionService.update(transaction);
    }

    /**
     * 支付操作
     *
     * @param notifyDataDto
     * @return
     */
    @Override
    public ResultDto transactionPay(NotifyDataDto notifyDataDto) {
        ResultDto resultDto = new ResultDto();
        String thirdLogNo = notifyDataDto.getOrderid();
        Transaction transaction = transactionService.findByThirdLogNo(thirdLogNo);

        if (null == transaction) {
            resultDto.setData(false);
            return resultDto;
        }
        if (!transaction.getTranType().equals(PayConstant.TranscationType.PAY)) {
            resultDto.setData(false);
            return resultDto;
        }
        if (notifyDataDto.getFlag().equals(PayConstant.NotifyFlag.FAILURE) ||
                notifyDataDto.getFlag().equals(PayConstant.NotifyFlag.UNKOWN)) {
            resultDto.setData(false);
            transaction.setTranStatus(PayConstant.TranStatus.FAILURE);
            return resultDto;
        }
        if (transaction.getTranStatus().equals(PayConstant.TranStatus.SUCCESS)) {
            resultDto.setData(true);
            return resultDto;
        }
        if (transaction.getTranStatus().equals(PayConstant.TranStatus.FAILURE)) {
            resultDto.setData(false);
            return resultDto;
        }

        if (transaction.getTranStatus().equals(PayConstant.TranStatus.NEED_CONFIRMED)) {
            MemberTransactionPasswordRequest memberTransactionPasswordRequest = new MemberTransactionPasswordRequest();
            memberTransactionPasswordRequest.setOutCustAcctId(transaction.getOutThirdPayAccountId());
            memberTransactionPasswordRequest.setSupAcctId(Constant.SUP_ACCT_ID);
            memberTransactionPasswordRequest.setOutThirdCustId(transaction.getOutAccountId());
            memberTransactionPasswordRequest.setOutCustName(transaction.getOutThirdPayAccountName());
            memberTransactionPasswordRequest.setInCustAcctId(transaction.getInThirdPayAccountId());
            memberTransactionPasswordRequest.setInThirdCustId(transaction.getInAccountId());
            memberTransactionPasswordRequest.setInCustName(transaction.getInThirdPayAccountName());
            memberTransactionPasswordRequest.setTranAmount(Double.toString(transaction.getTranAmount()));
            memberTransactionPasswordRequest.setTranFee(Double.toString(transaction.getHandFee()));
            memberTransactionPasswordRequest.setCcyCode(transaction.getCurrency());
            memberTransactionPasswordRequest.setThirdHtId(notifyDataDto.getOrderid());
            memberTransactionPasswordRequest.setReserve(thirdLogNo);
            memberTransactionPasswordRequest.setWebSign(notifyDataDto.getSign());
            //目前银行接口无法联调，先注释掉使用假数据保证前后台业务通过。后续银行接口正常之后再放开这段代码
            //特别重要：每个请求与响应都要记录到，数据库日志里表里（sys_operation_log），包括数据.这是交易排查的重要数据
            //PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.PAY,
            //        makeBackData(thirdLogNo, memberTransactionPasswordRequest));
            Object object = null;
            //try {
            //MemberTransactionPasswordResponse memberTransactionPasswordResponse = (MemberTransactionPasswordResponse)
            //        PAPay.sendMessage(thirdLogNo, memberTransactionPasswordRequest, MemberTransactionPasswordResponse.class);

            resultDto.setData(true);
            //object = memberTransactionPasswordResponse;
            updateTranscation(transaction, PayConstant.TranStatus.SUCCESS);
            List<String> listBill = new ArrayList<>();
            listBill.add(transaction.getBillNo());
            trdBillingService.paid(listBill);

            //目前银行接口无法联调，先注释掉使用假数据保证前后台业务通过。后续银行接口正常之后再放开这段代码
            /*} catch (NoAvailableConnectException e) {
                object = e.readRequest();
                transaction.setDescribeInfo(e.readRequest());
                updateTranscation(transaction, PayConstant.TranStatus.FAILURE);
                throw Exceptions.bizException(ErrorCodes.ERROR_PAY_AVAILABLE_CONNECT);
            } catch (OperationFailedException e) {
                object = e.getErrorMessage();
                resultDto.setErrorCode(ErrorCodes.ERROR_PAY_OPERATION.getCode());
                resultDto.setMsg(I18nMessageHelper.getI18nMessage(ErrorCodes.ERROR_PAY_OPERATION.getMessageKey(),null));
                resultDto.setData(e.getErrorMessage());
                transaction.setDescribeInfo(e.getErrorMessage().getRspMsg());
                updateTranscation(transaction, PayConstant.TranStatus.FAILURE);
            } catch (PayCommonException e) {
                object = e.readRequest();
                transaction.setDescribeInfo(e.readRequest());
                updateTranscation(transaction, PayConstant.TranStatus.FAILURE);
                throw Exceptions.bizException(ErrorCodes.ERROR_PAY_COMMON);
            } finally {
                PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.RESPONSE, PayAction.PAY,
                        makeBackData(thirdLogNo, object));
            }*/
            return resultDto;
        } else {
            return resultDto;
        }
    }

    /**
     * 通过客户id查询第三方账户id
     *
     * @param outCustomerId
     * @param inCustomerId
     * @return
     */
    @Override
    public ResultDto findThirdPayIdByCustomerId(int outCustomerId, int inCustomerId) {

        ResultDto resultDto = new ResultDto();
        Account outAccount = accountService.findAccountByCustomerId(outCustomerId);
        if (null == outAccount) {
            return resultDto;
        }
        ThirdPayAccount outThirdPayAccount = thirdPayAccountService.findByAccountIdAndThirdType(outAccount.getId(), PayConstant.PaymentType.PINGAN);
        if (null == outThirdPayAccount) {
            return resultDto;
        }

        Map map = new HashMap();
        map.put("outCustAcctId", outThirdPayAccount.getThirdPayId());
        map.put("outThirdCustId", outThirdPayAccount.getAccountId());
        map.put("outThirdPayName", outThirdPayAccount.getThirdPayName());
        map.put("Id", outThirdPayAccount.getId());

        Account inAccount = accountService.findAccountByCustomerId(inCustomerId);
        if (null == inAccount) {
            resultDto.setData(map);
            return resultDto;
        }
        ThirdPayAccount inThirdPayAccount = thirdPayAccountService.findByAccountIdAndThirdType(inAccount.getId(), PayConstant.PaymentType.PINGAN);
        if (null == inThirdPayAccount) {
            resultDto.setData(map);
            return resultDto;
        }
        map.put("inCustAcctId", inThirdPayAccount.getThirdPayId());
        map.put("inThirdCustId", inThirdPayAccount.getAccountId());
        map.put("inThirdPayName", inThirdPayAccount.getThirdPayName());
        resultDto.setData(map);
        return resultDto;
    }

    /**
     * 订单支付
     *
     * @param orderPaymentDto
     * @return resultDto
     */
    @Override
    public ResultDto orderPayment(OrderPaymentDto orderPaymentDto) {
        String thirdLogNo = SequenceGenerator.getThirdLogNo();
        AccountRecheckPaymentRequest accountRecheckPaymentRequest = new AccountRecheckPaymentRequest();
        accountRecheckPaymentRequest.setSupAcctId(Constant.SUP_ACCT_ID);
        accountRecheckPaymentRequest.setFuncFlag(orderPaymentDto.getFuncFlag());
        accountRecheckPaymentRequest.setOutCustAcctId(orderPaymentDto.getOutCustAcctId());
        accountRecheckPaymentRequest.setOutThirdCustId(orderPaymentDto.getOutThirdCustId());
        accountRecheckPaymentRequest.setInCustAcctId(orderPaymentDto.getInCustAcctId());
        accountRecheckPaymentRequest.setInThirdCustId(orderPaymentDto.getInThirdCustId());
        accountRecheckPaymentRequest.setHandFee(orderPaymentDto.getHandFee());
        accountRecheckPaymentRequest.setCcyCode(CcyCode.RMB);
        accountRecheckPaymentRequest.setPaySerialNo(thirdLogNo);
        accountRecheckPaymentRequest.setThirdHtCont(orderPaymentDto.getThirdHtId());
        accountRecheckPaymentRequest.setNote("");
        accountRecheckPaymentRequest.setReserve("");
        Object object = null;
        ResultDto resultDto = new ResultDto();
        AccountRecheckPaymentResponse accountRecheckPaymentResponse = new AccountRecheckPaymentResponse();
        //特别重要：每个请求与响应都要记录到，数据库日志里表里（sys_operation_log），包括数据.这是交易排查的重要数据
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.PAY, makeBackData(thirdLogNo, accountRecheckPaymentRequest));
        Transaction transaction = transactionService.findByBillNo(orderPaymentDto.getThirdHtId());
        if ((null != transaction)) {
            Double tranAmount = orderPaymentDto.getTranAmount() - transaction.getTranAmount();
            if (tranAmount < 0) {
                accountRecheckPaymentRequest.setOutCustAcctId(orderPaymentDto.getInCustAcctId());
                accountRecheckPaymentRequest.setOutThirdCustId(orderPaymentDto.getInThirdCustId());
                accountRecheckPaymentRequest.setInCustAcctId(orderPaymentDto.getOutCustAcctId());
                accountRecheckPaymentRequest.setInThirdCustId(orderPaymentDto.getOutThirdCustId());
            } else if (tranAmount == 0) {
                resultDto.setData(true);
                transaction.setIsDeleted(Boolean.TRUE);
                transactionService.update(transaction);
                OrderPaymentTransaction(thirdLogNo, orderPaymentDto);
                return resultDto;
            }
            accountRecheckPaymentRequest.setTranAmount(Math.abs(tranAmount) + "");
        }
        try {
            accountRecheckPaymentResponse = (AccountRecheckPaymentResponse)
                    PAPay.sendMessage(thirdLogNo,accountRecheckPaymentRequest,AccountRecheckPaymentResponse.class);
            object = accountRecheckPaymentResponse;
            if(null != transaction){
                transaction.setIsDeleted(Boolean.TRUE);
                transactionService.update(transaction);
            }
            List<String> listBill = new ArrayList<>();
            listBill.add(orderPaymentDto.getThirdHtId());
            trdBillingService.paid(listBill);
            OrderPaymentTransaction(thirdLogNo, orderPaymentDto);
        } catch (NoAvailableConnectException e) {
            object = e.getMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_AVAILABLE_CONNECT);
        } catch (OperationFailedException e) {
            object = e.getErrorMessage();
            resultDto.setErrorCode(ErrorCodes.ERROR_PAY_OPERATION.getCode());
            resultDto.setMsg(e.getErrorMessage().getRspCode() + " " + e.getErrorMessage().getRspMsg());
            resultDto.setData(Boolean.FALSE);
        } catch (PayCommonException e) {
            object = e.getMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_COMMON);
        } finally {
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.RESPONSE, PayAction.PAY,
                    BackDataUtil.makeMap(thirdLogNo, object));
        }
        return resultDto;
    }

    /**
     * 代理复核
     *
     * @param transaction
     * @return
     */
    @Override
    public String agentRecheck(Transaction transaction) {
        PlatformOperationPaymentRequest platformOperationPaymentRequest = new PlatformOperationPaymentRequest();
        platformOperationPaymentRequest.setSupAcctId(Constant.SUP_ACCT_ID);
        platformOperationPaymentRequest.setFuncFlag(PayConstant.PlatformOperationPayFlag.AGENT_RECHECK);
        platformOperationPaymentRequest.setPaySerialNo(transaction.getThirdLogNo());
        platformOperationPaymentRequest.setThirdHtId(transaction.getThirdBillNo());
        platformOperationPaymentRequest.setPayAmount(transaction.getTranAmount() + "");
        platformOperationPaymentRequest.setPayFee(transaction.getHandFee() + "");
        platformOperationPaymentRequest.setNote(transaction.getNote());
        platformOperationPaymentRequest.setReserve(transaction.getReserve());
        PlatformOperationPaymentResponse platformOperationPaymentResponse = null;
        Object object = null;
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.RESPONSE, PayAction.PAY,
                BackDataUtil.makeMap(transaction.getThirdLogNo(), platformOperationPaymentRequest));
        try {
            platformOperationPaymentResponse = (PlatformOperationPaymentResponse)
                    PAPay.sendMessage(transaction.getThirdLogNo(), platformOperationPaymentRequest, PlatformOperationPaymentResponse.class);
            object = platformOperationPaymentResponse;
            return transaction.getId();
        } catch (NoAvailableConnectException e) {
            object = e.getMessage();
        } catch (OperationFailedException e) {
            object = e.getErrorMessage();
        } catch (PayCommonException e) {
            object = e.getMessage();
        } finally {
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.RESPONSE, PayAction.PAY,
                    BackDataUtil.makeMap(transaction.getThirdLogNo(), object));
        }
        return null;
    }

    /**
     * 查询交易流水信息
     *
     * @param id
     * @param q
     * @param pageIndex
     * @param pageSize
     * @param beginDate
     * @param endDate
     * @param tranType
     * @return resultDto
     */
    @Override
    public ResultDto findTransaction(String id, String q, int pageIndex, int pageSize, String beginDate, String endDate, String tranType) {
        q = StringUtils.replaceSqlPattern(q);
        QueryParams params = new QueryParams(pageSize, pageIndex, q, null);
        params.put("ThirdPayAccountId", id);
        params.put("tranType", tranType);
        if ((!endDate.isEmpty()) && (!beginDate.isEmpty())) {
            params.put("beginDate", getyyyyMMdd(getDateStringByYYYY_MM_DDString(beginDate)));
            params.put("endDate", getyyyyMMdd(getDateStringByYYYY_MM_DDString(endDate)));
        }
        QResultDto qResultDto = transactionService.findByQuery(params);
        List<Transaction> transactionList = (List<Transaction>) qResultDto.getData();
        List<PayTransactionDto> list = new ArrayList<>();
        for (Transaction transaction : transactionList) {
            PayTransactionDto payTransactionDto = new PayTransactionDto();
            payTransactionDto.setId(transaction.getId());
            payTransactionDto.setTranTime(getyyyyMMddHHmmss(getDateByYYYYMMDDHHMMSSString(transaction.getTranDate() + transaction.getTranTime())));
            payTransactionDto.setBillNo(transaction.getBillNo());
            payTransactionDto.setTranAmount(transaction.getTranAmount() + transaction.getCurrency());
            payTransactionDto.setTranType(tranTypeConvert(transaction.getTranType()));
            payTransactionDto.setTranTypeCode(transaction.getTranType());
            if (PayConstant.TranscationType.PAY == transaction.getTranType()) {
                payTransactionDto.setThirdPayAccountName(transaction.getInThirdPayAccountName());
            }
            list.add(payTransactionDto);
        }
        qResultDto.setData(list);
        return qResultDto;
    }

    /**
     * 查询交易详情
     *
     * @param orderNo
     * @return
     */
    @Override
    public ResultDto findByOrderNo(String orderNo) {
        Transaction transaction = transactionService.select(orderNo);
        TransactionDetailsDto transactionDetailsDto = new TransactionDetailsDto();
        if (null != transaction) {
            transactionDetailsDto.setBillNo(transaction.getBillNo());
            transactionDetailsDto.setTranTime(getyyyyMMddHHmmss(getDateByYYYYMMDDHHMMSSString(transaction.getTranDate() + transaction.getTranTime())));
            transactionDetailsDto.setTranAmount(transaction.getTranAmount() + transaction.getCurrency());
            transactionDetailsDto.setTranStatus(transaction.getTranStatus());
            if ((PayConstant.TranscationType.WITHDRAWAL == transaction.getTranType()) || (PayConstant.TranscationType.PAY == transaction.getTranType())) {
                transactionDetailsDto.setAccountId(transaction.getOutThirdPayAccountId());
                transactionDetailsDto.setAccountName(transaction.getOutThirdPayAccountName());
                transactionDetailsDto.setBankName(transaction.getInAccountName());
                transactionDetailsDto.setBankCarNo(transaction.getInAccountId());
            } else if (PayConstant.TranscationType.RECHARGE == transaction.getTranType()) {
                transactionDetailsDto.setAccountId(transaction.getInThirdPayAccountId());
                transactionDetailsDto.setAccountName(transaction.getInThirdPayAccountName());
                transactionDetailsDto.setBankName(transaction.getOutAccountName());
                transactionDetailsDto.setBankCarNo(transaction.getOutAccountId());
            }
        }
        ResultDto resultDto = new ResultDto();
        resultDto.setData(transactionDetailsDto);
        return resultDto;
    }

    /**
     * 记录交易流水
     *
     * @param thirdLogNo
     * @param orderPaymentDto
     * @return
     */
    private Transaction OrderPaymentTransaction(String thirdLogNo, OrderPaymentDto orderPaymentDto) {
        Transaction transaction = new Transaction();
        transaction.setId(NOGenerator.getTranNo(PayConstant.TranscationType.PAY));
        transaction.setThirdLogNo(thirdLogNo);
        transaction.setTranType(PayConstant.TranscationType.PAY);
        transaction.setTranStatus(PayConstant.TranStatus.NEED_CONFIRMED);
        Date date = new Date();
        transaction.setCreateTime(date);
        transaction.setTranTime(DateGenerator.getHHmmss(date));
        transaction.setTranDate(DateGenerator.getyyyyMMdd(date));
        transaction.setCreateUserId(PrincipalUtils.getAccountId());
        transaction.setCurrency(orderPaymentDto.getCcyCode());
        transaction.setBillNo(orderPaymentDto.getThirdHtId());
        transaction.setHandFee(Double.parseDouble(orderPaymentDto.getHandFee()));
        transaction.setTranAmount(orderPaymentDto.getTranAmount());
        transaction.setOutAccountId(orderPaymentDto.getOutThirdCustId());
        transaction.setOutThirdPayAccountId(orderPaymentDto.getOutCustAcctId());
        transaction.setInAccountId(orderPaymentDto.getInThirdCustId());
        transaction.setInThirdPayAccountId(orderPaymentDto.getInCustAcctId());
        transaction.setThirdType(PayConstant.PaymentType.PINGAN);
        transaction.setIsDeleted(false);
        transactionService.insert(transaction);
        return transaction;
    }


    /**
     * 记录流水
     *
     * @param thirdLogNo
     * @param memberTransactionDto
     * @return
     */
    private Transaction memberTransactionPassword(String thirdLogNo, MemberTransactionDto memberTransactionDto) {
        Transaction transaction = new Transaction();
        transaction.setId(NOGenerator.getTranNo(PayConstant.TranscationType.PAY));
        transaction.setThirdLogNo(thirdLogNo);
        transaction.setTranType(PayConstant.TranscationType.PAY);
        transaction.setTranStatus(PayConstant.TranStatus.NEED_CONFIRMED);
        Date date = new Date();
        transaction.setCreateTime(date);
        transaction.setTranTime(DateGenerator.getHHmmss(date));
        transaction.setTranDate(DateGenerator.getyyyyMMdd(date));
        transaction.setCreateUserId(PrincipalUtils.getAccountId());
        transaction.setCurrency(memberTransactionDto.getCcyCode());
        transaction.setBillNo(memberTransactionDto.getThirdHtId());
        transaction.setHandFee(Double.parseDouble(memberTransactionDto.getTranFee()));
        transaction.setTranAmount(Double.parseDouble(memberTransactionDto.getTranAmount()));
        ThirdPayAccount thirdPayAccount = thirdPayAccountService.select(memberTransactionDto.getId());
        Account account = accountService.select(thirdPayAccount.getAccountId());
        transaction.setOutAccountBalance(bankCardService.getAccountBalance(memberTransactionDto.getOutCustAcctId()));
        transaction.setOutAccountId(memberTransactionDto.getOutThirdCustId());
        transaction.setOutThirdPayAccountId(memberTransactionDto.getOutCustAcctId());
        transaction.setOutThirdPayAccountName(memberTransactionDto.getOutCustName());
        transaction.setInAccountId(memberTransactionDto.getInThirdCustId());
        transaction.setInThirdPayAccountId(memberTransactionDto.getInCustAcctId());
        transaction.setInThirdPayAccountName(memberTransactionDto.getInCustName());
        transactionService.insert(transaction);
        return transaction;
    }

    private Map<String, Object> makeBackData(String thirdLogNo, Object obj) {
        Map<String, Object> map = new HashMap<>(16);
        map.put("thirdLogNo", thirdLogNo);
        if (null != obj) {
            map.put(obj.getClass().toString(), obj);
        }
        return map;
    }

}
